<?php
/**
 * Created by 99468
 * Date: 2017/9/10
 * Time: 20:03
 * Author: weblinuxgame
 * email : 994685563@qq.com
 * license : MTI
 **/

namespace EpgApp\modules\sdks\Image\base;

class ImageException extends \Exception
{
        protected static $errorCodeMap = array(
                         '[$file] dependent module error : [#]  not exists at line :[$line]'=>0,
                         '[$file] required function  not exists error :  [#]  at line :[$line]'=>1,
                         '[$file] params not match error : for required  function [#]  at line :[$line]'=>2,
                         '[$file] [#] file not exists error at line : [$line]'=>3,
                         '[$file] unknown error  at line : [#] [$line]'=>4,
                         '[$file] memory not enough error at line : [#] [$line]'=>5,
                         '[$file] [#] time out error at line: [$line]'=>6,
                         '[$file] [#] mode error at line : [$line]'=>7,
                         '[$file] [#] save path not exists error at line : [$line]'=>8,
                         '[$file] [#] type not support error at line : [$line]'=>9,
                         '[$file] [#] your image type unknown error at line : [$line]'=>10,
                         '[$file] [$func] << function  params missing   at line : [$line]'=>11,
                         '[$file] typeof -> [#] unknown or undefined  image type error at line : [$line] '=>12,
                         '[$file] [#] class init failed error at line : [$line] '=>13,
        );
        protected static $image_file_type = array(
                'gif'=>false,
                'png'=>false,
                'jpg'=>false,
                'bmp'=>false,
                'wbmp'=>false,
                'svg'=>false,
                'xmp'=>false,
        );
        const className = 'EpgApp\modules\sdker\Image\ImageException';

    /**
     * ImageException constructor.
     * @param string $message
     * @param int $code
     * @param \Throwable|null $previous
     */

        public function __construct($message = "", $code = 0,  $previous = null)
        {
            $trace = $this->getTrace();
            $len   = count($trace);
            $real_file = $trace[$len-1]['file'];
            $real_line = $trace[$len-1]['line'];
            $real_call_func = $trace[$len-1]['class'].$trace[$len-1]['type'].$trace[$len-1]['function'];
            // var_dump($trace);
            $message = str_replace('[$file]',$real_file,$message);
            $message = str_replace('[$line]',$real_line,$message);
            $message = str_replace('[$func]',$real_call_func,$message);
           // var_dump($message); // debug
            parent::__construct($message, $code, $previous);
        }

    /**
     * @param $funcName
     * @param bool $throw
     * @return bool
     * @throws ImageException
     */
        public static function function_exists($funcName,$throw=true)
        {
                if(empty($funcName))
                {
                    if($throw)
                    {
                        $error = 'function params empty error' ;
                        $code  = self::_code($error);
                        throw new ImageException(self::createMsgByCode($code,'function_exists'),$code);
                    }
                }
                if(!\function_exists($funcName))
                {
                    if($throw)
                    {
                        $error = 'function not exists' ;
                        $code  = self::_code($error);
                        throw new ImageException(self::createMsgByCode($code,$funcName),$code);
                    }
                }
                return true;
        }

    /**
     * @param $fileName
     * @param bool $throw
     * @return bool
     * @throws ImageException
     */
        public static function file_exists($fileName,$throw=true)
        {
            if(empty($fileName))
            {
                if($throw)
                {
                    $error = 'function params missing ' ;
                    $code  = self::_code($error) ;
                    // var_dump($code);
                    throw new ImageException(self::createMsgByCode($code,self::className.'::file_exists'),$code);
                }
            }
            if(!\file_exists($fileName))
            {
                if($throw)
                {
                    $error = 'file not exists' ;
                    $code  = self::_code($error) ;
                    throw new ImageException(self::createMsgByCode($code,$fileName),$code);
                }
                return false;
            }
            return true;
        }

    /**
     * @param {string} $type
     * @param {array|string|null} $handler
     * @param bool $throw
     * @return bool
     * @throws ImageException
     */
        public static function type_support($type,$handler=null,$throw=true)
        {
            if(empty($type))
            {
                if($throw)
                {
                    $error = 'function params missing' ;
                    $code  = self::_code($error);
                    throw new ImageException(self::createMsgByCode($code,'type_support'),$code);
                }
            }
            if($handler instanceof \Closure)
            {
                if(!$handler($type))
                {
                    $error = 'type not support';
                    $code  = self::_code($error);
                    throw new ImageException(self::createMsgByCode($code,$type), $code);
                }
                return true;
            }
            if(function_exists($handler))
            {
                if(call_user_func_array($handler,array($type,$throw)))
                {
                    return true ;
                }
            }
            if(is_array($handler))
            {
                $obj = null ;
                $func = null;
                if(count($handler)==2)
                {
                    if(is_object($handler[0]) && is_string($handler[1]))
                    {
                        $obj = $handler[0];
                        $func = $handler[1];
                    }
                    if(is_object($handler[1]) && is_string($handler[0]))
                    {
                        $obj = $handler[1];
                        $func = $handler[0];
                    }
                }
                if(!empty($obj) && !empty($func))
                {
                    if(\method_exists($obj,$func) && \call_user_func_array(array($obj,$func),array($type,$throw)))
                    {
                        return true;
                    }
                }
                else if($throw)
                {
                    $error = 'params not match';
                    $code = self::_code($error);
                   throw  new ImageException(self::createMsgByCode($code,\json_encode(array($type,$handler))),$code);
                }
            }
            if(empty($handler))
            {
                $fileInfo  = pathinfo($type);
                $ext       = isset($fileInfo['extension'])?$fileInfo['extension']:$type;
                foreach (self::$image_file_type as $key=>$value)
                {
                    // var_dump($key,$ext,$value);
                    if(($key == $type || $key == $ext) && true == $value)
                    {
                        return true;
                    }
                }
            }
            if($throw)
            {
                $error = 'type not support';
                $code  = self::_code($error);
                throw new ImageException(self::createMsgByCode($code,$type),$code);
            }
            return false;
        }

    /**
     * @param $fileName
     * @param bool $throw
     * @return bool
     */
        public static function isImageFile($fileName,$throw=true)
        {
          //  var_dump($fileName);
            self::emptyCheck($fileName,__METHOD__,$throw);
            $ext = '';
            if(self::file_exists($fileName))
            {
                $name = \pathinfo($fileName);

                if(!empty($name['extension']))
                {
                    $ext = $name['extension'];
                }
            }
            foreach (self::$image_file_type as $key =>$value )
            {
                if($key == $ext)
                {
                    return true;
                }
            }
            if($throw)
            {
                $error = 'undefined image type error';
                $code  = self::_code($error);
                new ImageException(self::createMsgByCode($code,$fileName),$code);
            }
            return false;
        }

    /**
     * @param array $files
     * @return bool
     */
        public static function setImageFileSupport($files=array())
        {
                if(empty($files))
                {
                    return false;
                }
                if(is_array($files))
                {
                    foreach ($files as $key =>$value)
                    {
                        if(is_string($key) && !empty($value) && is_bool($value))
                        {
                            self::$image_file_type[$key] = $value;
                        }
                        if(isset(self::$image_file_type[$key]) && null === $value )
                        {
                            unset(self::$image_file_type[$key]);
                        }
                    }
                    return true;
                }
                return false;
        }

    /**
     * @param $var
     * @param string $whichFunc
     * @param $throw
     * @return bool
     * @throws ImageException
     */
        public static function emptyCheck($var,$whichFunc='',$throw=false)
        {
            if(empty($var))
            {
                if($throw)
                {
                    $error = 'function params  missing';
                    $code  = self::_code($error);
                   // var_dump($code,$whichFunc);
                    throw new ImageException(static::createMsgByCode($code,$whichFunc),$code);
                }
                return true;
            }
            return false;
        }

    /**
     * @param $str
     * @return bool|mixed
     */
        public static function _code($str)
        {
            if(!empty($str) && is_string($str))
            {
                foreach ( self::$errorCodeMap as $key =>$value)
                {
                      // var_dump($key,"/.{0,}\b($str)\b.{0,}/");

                      $ret =  preg_match("/.{0,}\b($str)\b.{0,}/",$key);
                      if($ret)
                      {
                          return $value;
                      }
                }
            }
            return false;
        }

    /**
     * @param $code
     * @return bool|mixed
     */
        public static function _msg($code)
        {
            if(!empty($code) && is_numeric($code) )
            {
                foreach (self::$errorCodeMap as $key=>$value)
                {
                  if($code === $value)
                  {
                      return $key ;
                  }
                }
            }
            return false;
        }

    /**
     * @param $name
     * @param $arguments
     * @return array
     */
        public static function __callStatic($name, $arguments)
        {
                return static::$errorCodeMap ;
        }

    /**
     * @param $code
     * @param array $args
     * @return bool|mixed
     */
        public static function createMsgByCode($code,$args=array())
        {
            if(empty($code))
            {
                $code = 11 ;
            }
            $tpl = self::_msg($code);
           // var_dump($code,$tpl);  // debug
            if(!empty($args))
            {
                $msg = is_array($args) || is_object($args)? json_encode($args) : $args;
                $tpl = str_replace('[#]',$msg,$tpl);
            }
            return $tpl;
        }

    /**
     * @return string
     */
        public function __toString()
        {
            return self::className;
            // parent::__toString(); // TODO: Change the autogenerated stub
        }

}
